// Memory Management (内存管理) 示例
// 演示 Pascal 中内存管理的用法
program p_16_memory_management;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义指针类型
type
  PInteger = ^Integer;
  PString = ^String;
  
  // 定义记录类型
  TPerson = record
    Name: String[50];
    Age: Integer;
  end;
  PPerson = ^TPerson;

// 1. 使用New和Dispose管理简单数据类型
procedure DemoNewDispose;
var
  pInt: PInteger;
  pStr: PString;
begin
  WriteLn('  使用 New 和 Dispose:');
  
  // 分配整数内存
  New(pInt);
  pInt^ := 12345;
  WriteLn('    分配的整数值: ', pInt^);
  
  // 分配字符串内存
  New(pStr);
  pStr^ := 'Hello Dynamic Memory';
  WriteLn('    分配的字符串: ', pStr^);
  
  // 释放内存
  Dispose(pInt);
  Dispose(pStr);
  WriteLn('    内存已释放');
end;

// 2. 使用GetMem和FreeMem管理内存
procedure DemoGetMemFreeMem;
var
  pBuffer: Pointer;
  bufferSize: Integer = 100;
  i: Integer;
begin
  WriteLn('  使用 GetMem 和 FreeMem:');
  
  // 分配内存
  GetMem(pBuffer, bufferSize);
  WriteLn('    分配了 ', bufferSize, ' 字节的内存');
  
  // 使用内存（示例：填充前10个字节）
  for i := 0 to 9 do
    PByteArray(pBuffer)^[i] := i;
  
  Write('    前10个字节的值: ');
  for i := 0 to 9 do
    Write(PByteArray(pBuffer)^[i], ' ');
  WriteLn;
  
  // 释放内存
  FreeMem(pBuffer);
  WriteLn('    内存已释放');
end;

// 3. 使用AllocMem分配并清零内存
procedure DemoAllocMem;
var
  pBuffer: Pointer;
  bufferSize: Integer = 20;
  i: Integer;
begin
  WriteLn('  使用 AllocMem:');
  
  // 分配并清零内存
  AllocMem(pBuffer, bufferSize);
  
  Write('    前10个字节的值: ');
  for i := 0 to 9 do
    Write(PByteArray(pBuffer)^[i], ' ');
  WriteLn;
  
  // 释放内存
  FreeMem(pBuffer);
  WriteLn('    内存已释放');
end;

// 4. 动态管理记录类型
procedure DemoRecordMemoryManagement;
var
  pPerson: PPerson;
begin
  WriteLn('  动态管理记录类型:');
  
  // 分配记录内存
  New(pPerson);
  
  // 使用记录
  pPerson^.Name := '张三';
  pPerson^.Age := 30;
  
  WriteLn('    姓名: ', pPerson^.Name);
  WriteLn('    年龄: ', pPerson^.Age);
  
  // 释放记录内存
  Dispose(pPerson);
  WriteLn('    记录内存已释放');
end;

// 5. 演示内存泄漏问题
procedure DemoMemoryLeak;
var
  pInt: PInteger;
begin
  WriteLn('  内存泄漏演示:');
  
  // 分配内存但不释放 - 这会造成内存泄漏
  New(pInt);
  pInt^ := 999;
  WriteLn('    分配了内存但未释放，值为: ', pInt^);
  WriteLn('    注意：这会造成内存泄漏!');
  
  // 正确的做法应该是：
  // Dispose(pInt);
end;

// 程序主入口
begin
  WriteLn('=== Pascal 内存管理示例 ===');
  WriteLn;
  
  // 1. 使用New和Dispose
  WriteLn('1. 使用New和Dispose:');
  DemoNewDispose;
  
  WriteLn;
  
  // 2. 使用GetMem和FreeMem
  WriteLn('2. 使用GetMem和FreeMem:');
  DemoGetMemFreeMem;
  
  WriteLn;
  
  // 3. 使用AllocMem
  WriteLn('3. 使用AllocMem:');
  DemoAllocMem;
  
  WriteLn;
  
  // 4. 动态管理记录类型
  WriteLn('4. 动态管理记录类型:');
  DemoRecordMemoryManagement;
  
  WriteLn;
  
  // 5. 内存泄漏演示
  WriteLn('5. 内存泄漏演示:');
  DemoMemoryLeak;
  
  WriteLn;
  WriteLn('演示了 Pascal 中内存管理的用法');
  WriteLn('注意：实际编程中应避免内存泄漏');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.